#!/bin/bash

#############################################################
# 重复文件处理脚本 (delete_duplicates.sh) 
# 作者：Pedro.Pei
# 版本：1.0
# 日期：2023-12-20
#############################################################
#
# 功能说明：
#   此脚本用于查找并处理指定目录中的重复文件。脚本使用fdupes工具
#   查找重复文件，并提供三种处理方式：
#     1. 直接删除重复文件（保留每组的第一个文件）
#     2. 将重复文件移动到临时文件夹（更安全的选项）
#     3. 仅查看结果，不做任何处理
#
# 依赖要求：
#   - fdupes：用于查找重复文件
#   - bash：脚本运行环境
#
# 使用方法：
#   ./delete_duplicates.sh <目标目录>
#
# 参数说明：
#   <目标目录>：要检查重复文件的目录路径
#
# 处理流程：
#   1. 使用fdupes递归查找目标目录中的所有重复文件
#   2. 将结果保存到duplicates.txt文件中
#   3. 提示用户选择处理方式
#   4. 根据用户选择执行相应操作
#
# 注意事项：
#   - 删除模式会直接删除重复文件，请谨慎使用
#   - 移动模式会创建带时间戳的临时文件夹
#   - 处理详情会记录在duplicates.txt文件中
#   - 脚本需要fdupes工具支持，请确保已安装
#
# 示例：
#   ./delete_duplicates.sh /home/user/documents
#


# 检查是否安装了 fdupes
if ! command -v fdupes &> /dev/null; then
    echo "fdupes 未安装，请先安装 fdupes。" >&2
    exit 1
fi

# 检查是否提供了命令行参数
if [ $# -eq 0 ]; then
    echo "请提供要检查的目录路径作为参数。"
    echo "用法: \$0 <目标目录>"
    exit 1
fi

# 获取命令行参数作为目标目录路径
TARGET_DIR="$1"

# 检查是否提供了有效的目录路径
if [ ! -d "$TARGET_DIR" ]; then
    echo "提供的路径不是一个有效的目录: $TARGET_DIR"
    exit 1
fi

# 确保输出文件生成在目标目录
OUTPUT_FILE="$TARGET_DIR/duplicates.txt"

# 清空或创建输出文件
: > "$OUTPUT_FILE"  # 清空或创建输出文件

# 使用 fdupes 查找重复文件，递归检查所有子目录
start_time=$(date +%s)
echo "正在查找重复文件，请稍候..."
echo "开始时间: $(date)"
echo "目标目录: $TARGET_DIR"
fdupes -rSn "$TARGET_DIR" > "$OUTPUT_FILE.tmp"

# 检查 fdupes 是否成功执行
if [ $? -ne 0 ]; then
    echo "查找重复文件时发生错误。"
    rm -f "$OUTPUT_FILE.tmp"
    exit 1
fi

# 检查是否有重复文件
if [ ! -s "$OUTPUT_FILE.tmp" ]; then
    echo "未找到任何重复文件。"
    rm -f "$OUTPUT_FILE.tmp"  # 删除临时文件
    exit 0
fi

# 读取临时文件，处理每一组重复文件
echo "找到以下重复文件："
files=()
while IFS= read -r line; do
    # 如果是空行，表示一组重复文件结束
    if [[ -z "$line" ]]; then
        # 处理当前组的重复文件
        if [ ${#files[@]} -gt 1 ]; then
            # 输出重复文件的绝对路径
            for file in "${files[@]}"; do
                echo "重复文件: $file"
                echo "$file" >> "$OUTPUT_FILE"  # 将路径写入输出文件
            done
        fi
        # 清空数组，准备处理下一组
        files=()
    else
        # 跳过大小信息行（如 "9 bytes each:"）
        if [[ "$line" =~ ^[0-9]+\ bytes\ each: ]]; then
            continue
        fi
        # 将文件路径添加到当前组
        files+=("$line")
    fi
done < "$OUTPUT_FILE.tmp"

# 处理最后一组（如果文件末尾没有空行）
if [ ${#files[@]} -gt 1 ]; then
    for file in "${files[@]}"; do
        echo "重复文件: $file"
        echo "$file" >> "$OUTPUT_FILE"  # 将路径写入输出文件
    done
fi

# 提示用户选择处理方式
echo "请选择处理重复文件的方式："
echo "1. 直接删除重复文件（保留第一个）"
echo "2. 将重复文件移动到临时文件夹（更安全）"
echo "3. 不处理，仅查看结果"
read -p "请输入选择 (1/2/3): " choice

case "$choice" in
    1)
        echo "选择：直接删除重复文件"
        DELETE_MODE=true
        ;;
    2)
        echo "选择：移动重复文件到临时文件夹"
        DELETE_MODE=false
        # 创建临时文件夹
        TEMP_DIR="$TARGET_DIR/duplicate_files_$(date +%Y%m%d_%H%M%S)"
        mkdir -p "$TEMP_DIR"
        echo "临时文件夹已创建: $TEMP_DIR"
        ;;
    3)
        echo "用户选择不处理重复文件，脚本结束。"
        rm -f "$OUTPUT_FILE.tmp"  # 删除临时文件
        exit 0
        ;;
    *)
        echo "无效选择，脚本结束。"
        rm -f "$OUTPUT_FILE.tmp"  # 删除临时文件
        exit 1
        ;;
esac

# 处理重复文件（删除或移动）
if [ "$DELETE_MODE" = true ]; then
    echo "正在删除重复文件..."
else
    echo "正在移动重复文件到临时文件夹..."
fi

files=()
while IFS= read -r line; do
    # 如果是空行，表示一组重复文件结束
    if [[ -z "$line" ]]; then
        # 处理当前组的重复文件（保留第一个）
        if [ ${#files[@]} -gt 1 ]; then
            for file in "${files[@]:1}"; do
                if [ -e "$file" ]; then
                    if [ "$DELETE_MODE" = true ]; then
                        # 删除模式
                        echo "删除文件: $file"
                        rm -f "$file"
                        if [ $? -eq 0 ]; then
                            echo "已删除: $file"
                        else
                            echo "无法删除: $file"
                        fi
                    else
                        # 移动模式
                        filename=$(basename "$file")
                        # 如果目标文件已存在，添加数字后缀
                        counter=1
                        target_file="$TEMP_DIR/$filename"
                        while [ -e "$target_file" ]; do
                            name_without_ext="${filename%.*}"
                            ext="${filename##*.}"
                            if [ "$name_without_ext" = "$filename" ]; then
                                # 没有扩展名
                                target_file="$TEMP_DIR/${filename}_$counter"
                            else
                                # 有扩展名
                                target_file="$TEMP_DIR/${name_without_ext}_$counter.$ext"
                            fi
                            ((counter++))
                        done
                        
                        echo "移动文件: $file -> $target_file"
                        mv "$file" "$target_file"
                        if [ $? -eq 0 ]; then
                            echo "已移动: $file"
                        else
                            echo "无法移动: $file"
                        fi
                    fi
                else
                    echo "文件不存在: $file"
                fi
            done
        fi
        # 清空数组，准备处理下一组
        files=()
    else
        # 跳过大小信息行（如 "9 bytes each:"）
        if [[ "$line" =~ ^[0-9]+\ bytes\ each: ]]; then
            continue
        fi
        # 将文件路径添加到当前组
        files+=("$line")
    fi
done < "$OUTPUT_FILE.tmp"

# 处理最后一组（如果文件末尾没有空行）
if [ ${#files[@]} -gt 1 ]; then
    for file in "${files[@]:1}"; do
        if [ -e "$file" ]; then
            if [ "$DELETE_MODE" = true ]; then
                # 删除模式
                echo "删除文件: $file"
                rm -f "$file"
                if [ $? -eq 0 ]; then
                    echo "已删除: $file"
                else
                    echo "无法删除: $file"
                fi
            else
                # 移动模式
                filename=$(basename "$file")
                # 如果目标文件已存在，添加数字后缀
                counter=1
                target_file="$TEMP_DIR/$filename"
                while [ -e "$target_file" ]; do
                    name_without_ext="${filename%.*}"
                    ext="${filename##*.}"
                    if [ "$name_without_ext" = "$filename" ]; then
                        # 没有扩展名
                        target_file="$TEMP_DIR/${filename}_$counter"
                    else
                        # 有扩展名
                        target_file="$TEMP_DIR/${name_without_ext}_$counter.$ext"
                    fi
                    ((counter++))
                done
                
                echo "移动文件: $file -> $target_file"
                mv "$file" "$target_file"
                if [ $? -eq 0 ]; then
                    echo "已移动: $file"
                else
                    echo "无法移动: $file"
                fi
            fi
        else
            echo "文件不存在: $file"
        fi
    done
fi

# 清理临时文件
rm -f "$OUTPUT_FILE.tmp"

end_time=$(date +%s)
duration=$((end_time - start_time))

if [ "$DELETE_MODE" = true ]; then
    echo "重复文件删除完成！"
else
    echo "重复文件移动完成！"
    echo "临时文件夹路径: $TEMP_DIR"
    echo "请检查临时文件夹中的文件，确认无误后可手动删除。"
fi

echo "处理耗时: ${duration}秒"

echo "处理详情已写入 $OUTPUT_FILE 文件。"
